home *** CD-ROM | disk | FTP | other *** search
- #include <crtdbg.h>
-
- #include <windows.h>
-
-
- namespace Windows95 {
-
- #include <svrapi.h>
-
- };
-
-
- #include <lmcons.h>
- #include <lmserver.h>
- #include <lmapibuf.h>
- #include <vfw.h>
-
- #define BUILDING_VDSVRLNK_DLL
- #include "vdserver.h"
-
- typedef struct VDubPostedFrameserver {
- HWND hwndServer;
- int active_connects;
- char name[56];
- } VDubPostedFrameserver;
-
- #define MAXIMUM_FRAMESERVERS (256)
-
- typedef struct VDubSharedHeap {
- char comp_name[16];
- int total_frameservers;
- int last_alloc;
- DWORD next_mmapID;
- VDubPostedFrameserver fs_table[MAXIMUM_FRAMESERVERS];
- } VDubSharedHeap;
-
- ////////////////////////////////////////////
-
- VDubSharedHeap *heap;
- HANDLE hHeap;
- HANDLE hMutex;
-
- ////////////////////////////////////////////
-
- typedef int (APIENTRY *LPNETSERVERGETINFO95)(
- const char FAR * pszServer,
- short sLevel,
- char FAR * pbBuffer,
- unsigned short cbBuffer,
- unsigned short FAR * pcbTotalAvail);
-
- typedef NET_API_STATUS (APIENTRY *LPNETSERVERGETINFONT)(
- LPWSTR servername,
- DWORD level,
- LPBYTE *bufptr);
-
- static void InitComputerAlias() {
- union {
- struct Windows95::server_info_50 si_95;
- char buf[2048];
- } si;
- unsigned short needed_size;
- HMODULE hDll = NULL;
- FARPROC fpNetServerGetInfo = NULL;
-
- // For Windows 95, NetServerGetInfo() is in SVRAPI.DLL
- // For Windows NT, NetServerGetInfo() is in NETAPI32.DLL
- //
- // Rather than test for the OS as Microsoft suggests, we simply
- // try SVRAPI.DLL first, and then NETAPI32. If both fail, then
- // fake a computer name with 'ANON' and then 8 hex digits of the
- // current tick value.
-
- if (hDll = LoadLibrary("svrapi.dll")) {
- fpNetServerGetInfo = GetProcAddress(hDll, "NetServerGetInfo");
-
- if (fpNetServerGetInfo && !((LPNETSERVERGETINFO95)fpNetServerGetInfo)(NULL, 50, (char *)&si, sizeof si, &needed_size)) {
- strncpy(heap->comp_name, si.si_95.sv50_name, sizeof heap->comp_name);
- heap->comp_name[sizeof heap->comp_name-1] = 0;
-
- FreeLibrary(hDll);
- return;
- }
-
- FreeLibrary(hDll);
- }
-
- // Okay, that didn't work -- try Windows NT/2000.
-
- if (!fpNetServerGetInfo && (hDll = LoadLibrary("netapi32.dll"))) {
- SERVER_INFO_100 *psi100;
-
- fpNetServerGetInfo = GetProcAddress(hDll, "NetServerGetInfo");
- if (fpNetServerGetInfo && !((LPNETSERVERGETINFONT)fpNetServerGetInfo)(NULL, 100, (LPBYTE *)&psi100)) {
-
- WideCharToMultiByte(CP_ACP, 0, (LPWSTR)psi100->sv100_name, -1, heap->comp_name, sizeof heap->comp_name, NULL, NULL);
- // strncpy(heap->comp_name, psi100->sv100_name, sizeof heap->comp_name);
- // heap->comp_name[sizeof heap->comp_name-1] = 0;
-
- void *lpNetApiBufferFree;
-
- if (lpNetApiBufferFree = GetProcAddress(hDll, "NetApiBufferFree"))
- ((NET_API_STATUS (APIENTRY *)(LPVOID ))lpNetApiBufferFree)(psi100);
-
- FreeLibrary(hDll);
- return;
- }
-
- FreeLibrary(hDll);
- }
-
- // Ugh.
-
- wsprintf(heap->comp_name, "Anon%08lx", GetTickCount());
- }
-
- static BOOL InitSharedSpace() {
- BOOL fInit;
-
- //////////
-
- hHeap = CreateFileMapping( (HANDLE)0xFFFFFFFF,
- NULL,
- PAGE_READWRITE,
- 0,
- sizeof(VDubSharedHeap),
- "VirtualDub Server System Window");
-
- if (hHeap == NULL) return FALSE;
-
- _RPT0(0,"shared heap created\n");
-
- fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
-
- heap = (VDubSharedHeap *)MapViewOfFile(
- hHeap,
- FILE_MAP_WRITE,
- 0,
- 0,
- 0);
-
- if (!heap) {
- CloseHandle(hHeap);
- return FALSE;
- }
-
- _RPT0(0,"heap mapped into subspace... preparing to go to warp.\n");
-
- if (!(hMutex = CreateMutex(NULL, FALSE, "VirtualDub Server System Mutex")))
- return FALSE;
-
- _RPT0(0,"mutex obtained\n");
-
- if (!fInit) return TRUE;
-
- memset(heap, 0, sizeof VDubSharedHeap);
-
- InitComputerAlias();
-
- return TRUE;
- }
-
- // Are you a Ranma 1/2 fan?
-
- static void ranko() {
- _RPT1(0,"server: lock mutex %p\n", hMutex);
- WaitForSingleObject(hMutex, INFINITE);
- }
-
- static void ranma() {
- _RPT1(0,"server: unlock mutex %p\n", hMutex);
- if (!ReleaseMutex(hMutex))
- _RPT0(0,"Hey! I didn't own the mutex!\n");
- }
-
- ////////////////////////////////////////////
-
- //extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HANDLE hModule, ULONG ulReason, LPVOID lpReserved);
-
- HMODULE ghModule;
-
- BOOL APIENTRY DllMain(HANDLE hModule, ULONG ulReason, LPVOID lpReserved) {
-
- switch(ulReason) {
- case DLL_PROCESS_ATTACH:
- ghModule = (HMODULE)hModule;
-
- _RPT0(0,"Process attach\n");
-
- return InitSharedSpace();
-
- case DLL_PROCESS_DETACH:
- UnmapViewOfFile(heap);
- CloseHandle(hHeap);
- break;
- }
-
- return TRUE;
- }
-
- /////////////////////////////////////////////
-
- class CVDubAnimConnection : public IVDubAnimConnection {
- private:
- VDubPostedFrameserver *frameserver;
- HANDLE hArena;
- char *arena;
- long lArenaSize;
- DWORD dwSessionID;
- long lFrameSize;
-
- public:
- CVDubAnimConnection(VDubPostedFrameserver *);
- ~CVDubAnimConnection();
-
- BOOL init();
-
- BOOL hasAudio();
- BOOL readStreamInfo(AVISTREAMINFO *lpsi, BOOL fAudio, long *lpFirst, long *lpLast);
- int readFormat(void *ptr, BOOL fAudio);
- int readVideo(long lSample, void *lpBuffer);
- int readAudio(long lSample, long lCount, void *lpBuffer, long cbBuffer, long *lplBytes, long *lplSamples);
- };
-
-
- ///////////////////////////////////////////
-
- CVDubAnimConnection::CVDubAnimConnection(VDubPostedFrameserver *vdpf) {
- frameserver = vdpf;
- dwSessionID = 0;
- hArena = INVALID_HANDLE_VALUE;
- arena = NULL;
- }
-
- CVDubAnimConnection::~CVDubAnimConnection() {
- if (dwSessionID) SendMessage(frameserver->hwndServer, VDSRVM_CLOSE, 0, dwSessionID);
-
- if (arena) UnmapViewOfFile(arena);
- if (hArena) CloseHandle(hArena);
-
- --frameserver->active_connects;
- }
-
- BOOL CVDubAnimConnection::init() {
- LONG lArenaSize;
- char buf[16];
- DWORD mmapID;
-
- // find out how big of an arena we need
-
- lArenaSize = SendMessage(frameserver->hwndServer, VDSRVM_BIGGEST, 0, 0);
-
- if (!lArenaSize) return FALSE;
-
- // create a name for us
-
- ranko();
- wsprintf(buf, "VDUBF%08lx", mmapID = heap->next_mmapID++);
- ranma();
-
- // create a shared arena and map a window for us
-
- hArena = CreateFileMapping(
- (HANDLE)0xFFFFFFFF,
- NULL,
- PAGE_READWRITE,
- 0,
- lArenaSize,
- buf);
-
- if (!hArena) return FALSE;
-
- _RPT0(0,"Have arena.\n");
-
- arena = (char *)MapViewOfFile(hArena, FILE_MAP_WRITE, 0, 0, lArenaSize);
-
- if (!arena) return FALSE;
-
- _RPT0(0,"Arena mapped.\n");
-
- // hail the server
-
- dwSessionID = SendMessage(frameserver->hwndServer, VDSRVM_OPEN, lArenaSize, mmapID);
-
- if (!dwSessionID) return FALSE; // no response, Captain
-
- _RPT0(0,"Server responded.\n");
-
- // on screen! get me the video format!
-
- if (SendMessage(frameserver->hwndServer, VDSRVM_REQ_FORMAT, 0, dwSessionID) <= 0)
- return FALSE;
-
- {
- BITMAPINFOHEADER *bmih = (BITMAPINFOHEADER *)arena;
-
- lFrameSize = bmih->biSizeImage;
- }
-
- _RPT0(0,"Connect!\n");
-
- return TRUE;
- }
-
- BOOL CVDubAnimConnection::hasAudio() {
- return VDSRVERR_OK == SendMessage(frameserver->hwndServer, VDSRVM_REQ_STREAMINFO, 1, dwSessionID);
- }
-
- BOOL CVDubAnimConnection::readStreamInfo(AVISTREAMINFO *lpsi, BOOL fAudio, long *lpFirst, long *lpLast) {
- if (VDSRVERR_OK == SendMessage(frameserver->hwndServer, VDSRVM_REQ_STREAMINFO, !!fAudio, dwSessionID)) {
- if (lpsi) memcpy(lpsi, arena+8, sizeof(AVISTREAMINFO));
- if (lpFirst) *lpFirst = *(long *)(arena+0);
- if (lpLast) *lpLast = *(long *)(arena+4);
- return TRUE;
- }
- return FALSE;
- }
-
- int CVDubAnimConnection::readFormat(void *ptr, BOOL fAudio) {
- int err;
-
- err = SendMessage(frameserver->hwndServer, VDSRVM_REQ_FORMAT, !!fAudio, dwSessionID);
-
- if (err<0) return err;
-
- if (ptr) memcpy(ptr, arena, err);
-
- return err;
- }
-
- int CVDubAnimConnection::readVideo(long lSample, void *lpBuffer) {
- int err;
-
- _RPT0(0,"Sending message...\n");
- if (VDSRVERR_OK != (err = SendMessage(frameserver->hwndServer, VDSRVM_REQ_FRAME, lSample, dwSessionID)))
- return err;
-
- _RPT2(0,"Copying %ld bytes to user buffer from arena %P\n", lFrameSize, arena);
- memcpy(lpBuffer, arena, lFrameSize);
- _RPT0(0,"Copy completed.\n");
-
- return VDSRVERR_OK;
- }
-
- int CVDubAnimConnection::readAudio(long lSample, long lCount, void *lpBuffer, long cbBuffer, long *lplBytes, long *lplSamples) {
- int err;
-
- *(long *)(arena+0) = lCount;
- *(long *)(arena+4) = cbBuffer;
-
- if (VDSRVERR_OK != (err = SendMessage(frameserver->hwndServer, lpBuffer?VDSRVM_REQ_AUDIO:VDSRVM_REQ_AUDIOINFO, lSample, dwSessionID)))
- return err;
-
- if (lplSamples) *lplSamples = *(long *)(arena + 4);
- if (lplBytes) *lplBytes = *(long *)(arena + 0);
-
- if (lpBuffer) memcpy(lpBuffer, arena+8, *lplBytes);
-
- return VDSRVERR_OK;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // CVDubServerLink
- //
- /////////////////////////////////////////////////////////////////////////////
-
- class CVDubServerLink : public IVDubServerLink {
- public:
- void GetComputerName(char *buf);
- IVDubAnimConnection * FrameServerConnect(char *fs_name);
- void FrameServerDisconnect(IVDubAnimConnection *);
- int CreateFrameServer(char *name, HWND hwndServer);
- void DestroyFrameServer(int handle);
- };
-
- static CVDubServerLink i_dubserver;
-
- void CVDubServerLink::GetComputerName(char *buf) {
- lstrcpy(buf, heap->comp_name);
- }
-
- IVDubAnimConnection *CVDubServerLink::FrameServerConnect(char *fs_name) {
- int i;
- char c,*s;
- CVDubAnimConnection *cvdac;
-
- // look for a slash (/) that delimits the computer name
-
- _RPT1(0,"Looking for server [%s]\n",fs_name);
-
- s = fs_name;
- while(c=*s++) if (c=='/') {
- char *s1, *s2, d;
-
- // we found the slash... now compare that to our computer name
-
- s1 = fs_name;
- s2 = heap->comp_name;
-
- do {
- c = *s1++;
- d = *s2++;
- } while(c==d && c!='/' && d);
-
- if (c!='/' || d)
- return NULL; // not our computer, and we don't do remote yet
-
- // yay! it's us!
-
- break;
- }
-
- if (!c) s=fs_name;
-
- // look through the list and see if we can spot the server
-
- _RPT1(0,"Computer name ok, looking for server [%s]\n", s);
-
- ranko();
-
- for(i=0; i<MAXIMUM_FRAMESERVERS; i++) {
- if (heap->fs_table[i].hwndServer && !stricmp(heap->fs_table[i].name, s))
- break;
- }
-
- if (i >= MAXIMUM_FRAMESERVERS) {
- _RPT0(0,"Computer not found\n");
- ranma();
- return NULL;
- }
-
- // hey! we spotted the server! now lock it before it goes
- // away!
-
- _RPT0(0,"Server found\n");
-
- ++heap->fs_table[i].active_connects;
-
- // allocate a CVDubAnimConnection
-
- if (cvdac = new CVDubAnimConnection(&heap->fs_table[i])) {
- // try to initialize it
-
- if (!cvdac->init()) {
- delete cvdac;
- cvdac = NULL;
- }
- } else --heap->fs_table[i].active_connects;
-
- ranma();
-
- return cvdac;
- }
-
- void CVDubServerLink::FrameServerDisconnect(IVDubAnimConnection *idac) {
- delete (CVDubAnimConnection *)idac;
- }
-
- int CVDubServerLink::CreateFrameServer(char *name, HWND hwndServer) {
- int i;
-
- if (heap->total_frameservers >= MAXIMUM_FRAMESERVERS)
- return -1;
-
- ranko();
-
- i = heap->last_alloc;
- while(heap->fs_table[i].active_connects || heap->fs_table[i].hwndServer)
- i = (i+1) % MAXIMUM_FRAMESERVERS;
-
- heap->fs_table[i].hwndServer = hwndServer;
- strncpy(heap->fs_table[i].name, name, sizeof heap->fs_table[i].name);
-
- heap->fs_table[i].name[(sizeof heap->fs_table[i].name)-1] = 0;
-
- heap->last_alloc = i;
-
- ranma();
-
- return i;
- }
-
- void CVDubServerLink::DestroyFrameServer(int handle) {
- if (handle<0 || handle>=MAXIMUM_FRAMESERVERS)
- return;
-
- ranko();
-
- heap->fs_table[handle].hwndServer = NULL;
-
- ranma();
- }
-
- __declspec(dllexport) IVDubServerLink *GetDubServerInterface() {
- return &i_dubserver;
- }
-